package com.ee.chat.api.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ee.chat.api.common.CommonService;
import com.ee.chat.api.service.IBaseService;
import com.ee.chat.api.service.IDynamicService;
import com.ee.chat.api.service.IHostService;
import com.ee.chat.common.bean.Result;
import com.ee.chat.common.dao.*;
import com.ee.chat.common.entity.Banner;
import com.ee.chat.common.entity.Host;
import com.ee.chat.common.entity.HostCallContent;
import com.ee.chat.common.service.IYieldService;
import com.ee.chat.common.util.ConstantsUtil;
import com.ndhutu.ee.util.PageUtil;
import com.ndhutu.ee.util.StringUtil;
import com.ndhutu.ee.util.map.GISUtil;
import com.ndhutu.ee.util.map.Gps;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class HostServiceImpl implements IHostService {
    @Resource
    HostMapper hostMapper;
    @Resource
    BannerMapper bannerMapper;
    @Resource
    CommonService commonService;
    @Resource(name = "stringRedisTemplate")
    StringRedisTemplate redisTemplate;
    @Resource
    UserDynamicMapper userDynamicMapper;
    @Resource
    UserMapper userMapper;
    @Resource
    UserDynamicBuyLogMapper userDynamicBuyLogMapper;
    @Resource
    UserWalletMapper userWalletMapper;
    @Resource
    HostDynamicConfigMapper hostDynamicConfigMapper;
    @Resource
    HostCallContentMapper hostCallContentMapper;
    @Resource
    UserLableMapper userLableMapper;
    @Resource
    UserGiftBuyLogMapper userGiftBuyLogMapper;
    @Resource
    IDynamicService dynamicService;
    @Resource
    UserVipMapper userVipMapper;
    @Resource
    IBaseService baseService;
    @Resource
    UserOperationLogMapper userOperationLogMapper;
    @Resource
    IYieldService yieldService;

    @Override
    public Result getTitleHosts(String token, Integer page, Integer limit) throws Exception {
        Map<String, Object> data = new HashMap<>();

        Integer userId = commonService.getUserId(token);
        List<Map<String, Object>> hosts = hostMapper.getHostTitles(userId, PageUtil.getOffset(page, limit), limit);

        //记录已返回的主播数据
        String key = ConstantsUtil.USER_HISTORY_TITLE + userId;
        redisTemplate.expire(key, -1, TimeUnit.MINUTES);
        List<String> userIds = new ArrayList<>(hosts.size());
        for(Map<String, Object> host : hosts){
            userIds.add(host.get("userId")+"");
        }
        redisTemplate.opsForSet().add(key, userIds.toArray(new String[userIds.size()]));

        data.put("users", hosts);
        return Result.returnSuccess(data);
    }

    @Override
    public Result getBanners(String token) throws Exception {
        Map<String, Object> data = new HashMap<>();

        QueryWrapper<Banner> wrapper = new QueryWrapper<>();
        wrapper.eq("status", 0);
        wrapper.orderByDesc("order_id");
        List<Banner> banners = bannerMapper.selectList(wrapper);

        data.put("banners", banners);
        return Result.returnSuccess(data);
    }

    @Override
    public Result getTypeHosts(String token, Integer type, Integer page, Integer limit, String location, String extra) throws Exception {
        Map<String, Object> data = new HashMap<>();

        Integer userId = commonService.getUserId(token);
        Host host = hostMapper.selectByUserId(userId);

        List<Map<String, Object>> hosts = new ArrayList<>();
        Set<String> historyUserIds = new HashSet<>();
        switch (type){
            case 0:  //热门
                if(userId != null){
                    String titleKey = ConstantsUtil.USER_HISTORY_TITLE + userId;
                    String hotKey = ConstantsUtil.USER_HISTORY_HOT + userId;

                    if(page == 1){  //清理数据
                        redisTemplate.expire(hotKey, -1, TimeUnit.MINUTES);

                    }else{  //当排除部分数据时，每次都从第一页查询
                        page = 1;
                    }
                    historyUserIds.addAll(redisTemplate.opsForSet().members(titleKey));
                    historyUserIds.addAll(redisTemplate.opsForSet().members(hotKey));
                }

                hosts = hostMapper.getHotHosts(historyUserIds, PageUtil.getOffset(page, limit), limit);

                //记录已返回值
                if(userId != null && hosts.size() > 0){
                    Set<String> userIds = new HashSet<>();
                    for(Map<String, Object> h : hosts){
                        userIds.add(h.get("userId")+"");
                    }
                    String hotKey = ConstantsUtil.USER_HISTORY_HOT + userId;
                    redisTemplate.opsForSet().add(hotKey, userIds.toArray(new String[userIds.size()]));
                }
                break;

            case 1: //在线
                if(userId != null){
                    String onlineKey = ConstantsUtil.USER_HISTORY_ONLINE + userId;

                    if(page == 1){  //清理数据
                        redisTemplate.expire(onlineKey, -1, TimeUnit.MINUTES);

                    }else{  //当排除部分数据时，每次都从第一页查询
                        page = 1;
                    }
                    historyUserIds.addAll(redisTemplate.opsForSet().members(onlineKey));
                }

                if(host == null){   //查看主播列表
                    hosts = hostMapper.getHostByOnlineTime(historyUserIds, PageUtil.getOffset(page, limit), limit);
                }else{  //查看用户列表
                    hosts = hostMapper.getUserByOnlineTime(historyUserIds, PageUtil.getOffset(page, limit), limit);
                }

                //记录已返回值
                if(userId != null && hosts.size() > 0){
                    Set<String> userIds = new HashSet<>();
                    for(Map<String, Object> h : hosts){
                        userIds.add(h.get("userId")+"");
                    }
                    String onlineKey = ConstantsUtil.USER_HISTORY_ONLINE + userId;
                    redisTemplate.opsForSet().add(onlineKey, userIds.toArray(new String[userIds.size()]));
                }
                break;

            case 2: //新人
                if(userId != null){
                    String newKey = ConstantsUtil.USER_HISTORY_NEW + userId;

                    if(page == 1){  //清理数据
                        redisTemplate.expire(newKey, -1, TimeUnit.MINUTES);

                    }else{  //当排除部分数据时，每次都从第一页查询
                        page = 1;
                    }
                    historyUserIds.addAll(redisTemplate.opsForSet().members(newKey));
                }

                if(host == null){
                    hosts = hostMapper.getHostByCreateTime(historyUserIds, PageUtil.getOffset(page, limit), limit);
                }else{
                    hosts = hostMapper.getUserByCreateTime(historyUserIds, PageUtil.getOffset(page, limit), limit);
                }

                //记录已返回值
                if(userId != null && hosts.size() > 0){
                    Set<String> userIds = new HashSet<>();
                    for(Map<String, Object> h : hosts){
                        userIds.add(h.get("userId")+"");
                    }
                    String newKey = ConstantsUtil.USER_HISTORY_NEW + userId;
                    redisTemplate.opsForSet().add(newKey, userIds.toArray(new String[userIds.size()]));
                }
                break;

            case 3://关注
                if(userId != null){
                    hosts = hostMapper.getFocusUsers(userId, PageUtil.getOffset(page, limit), limit);
                }
                break;

            case 4: //同城
                if(StringUtil.isEmpty(location)){
                    return Result.returnFailure("经纬度不能为空");
                }
                //ios设备，84坐标系转bd坐标系
                Map<String, Object> extraMap = JSONObject.parseObject(extra, Map.class);
                if("iOS".equals(extraMap.get("sysType"))){
                    Double lng = Double.parseDouble(location.split(",")[0]);    //经度
                    Double lat = Double.parseDouble(location.split(",")[1]);    //维度
                    Gps gps = GISUtil.gps84_To_Bd09(lat, lng);
                    if(gps != null){    //境外ip不予处理
                        lat = gps.getLat();
                        lng = gps.getLng();
                        location = lng + "," + lat;
                    }
                }

                //更新用户位置
                if(userId != null){
                    userMapper.updateUserByLnglat(userId, location);
                }

                if(host == null){
                    hosts = hostMapper.getLocalHosts(location, PageUtil.getOffset(page, limit), limit);
                }else{
                    hosts = hostMapper.getLocalUsers(location, PageUtil.getOffset(page, limit), limit);
                }

                //判断是否打过招呼
                for(Map<String, Object> h : hosts){
                    if(userId == null){
                        h.put("call", 0);
                    }else{
                        String key = ConstantsUtil.USER_LOCAL_SAYHELLO + userId + ":" + h.get("userId");
                        Object call = redisTemplate.opsForHash().get(key, "call");
                        h.put("call", call == null ? 0 : 1);
                    }
                }
                break;

            case 5://粉丝
                if(userId != null){
                    hosts = hostMapper.getFansUsers(userId, PageUtil.getOffset(page, limit), limit);
                }

                break;
            default:
                return Result.returnFailure("非法参数");
        }

        data.put("users", hosts);
        return Result.returnSuccess(data);
    }

    @Override
    public Result getRandomOnlineHost(String token) throws Exception {
        Map<String, Object> data = new HashMap<>();
        Integer userId = commonService.getUserId(token);

        Set<String> hostoryUserIds = new HashSet<>();
        if(userId != null){
            String key = ConstantsUtil.USER_HISTORY_RANDOM + userId;
            hostoryUserIds = redisTemplate.opsForSet().members(key);
        }
        Map<String, Object> onlineHost = hostMapper.getRandomOnlineHost(hostoryUserIds);

        /**
         * 当在线主播很少的情况下，可重复循环
         */
        if(onlineHost == null){
            //清空用户已返回的随机在线主播数据
            redisTemplate.expire(ConstantsUtil.USER_HISTORY_RANDOM+":"+userId, -1, TimeUnit.MINUTES);
            onlineHost = hostMapper.getRandomOnlineHost(new HashSet<>());
        }
        if(onlineHost != null) {
            //映像标签
            List<Map<String, Object>> lables = userLableMapper.getUserLables(Integer.parseInt(onlineHost.get("userId").toString()));
            onlineHost.put("lables", lables);
        }

        if(userId != null && onlineHost != null) {
            String key = ConstantsUtil.USER_HISTORY_RANDOM + userId;
            redisTemplate.opsForSet().add(key, onlineHost.get("userId")+"");
        }

        data.put("users", onlineHost);
        return Result.returnSuccess(data);
    }

    @Override
    public Result sayHello(String token, Integer toUserId) throws Exception {
        Integer userId = commonService.getUserId(token);

        String key = ConstantsUtil.USER_LOCAL_SAYHELLO + userId + ":" + toUserId;
        redisTemplate.opsForHash().put(key, "call", "1");
        LocalDateTime midNight = LocalDateTime.now().plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
        long mill = ChronoUnit.SECONDS.between(LocalDateTime.now(), midNight);
        redisTemplate.expire(key, mill, TimeUnit.SECONDS);

        return Result.returnSuccess(null);
    }

    @Override
    public Result getHostCallContents(String token, Integer status, Integer page, Integer limit) throws Exception {
        Map<String, Object> data = new HashMap<>();

        Integer userId = commonService.getUserId(token);
        Host host = hostMapper.selectByUserId(userId);
        Page<Map<String, Object>> p = new Page<>(page, limit);
        IPage<Map<String, Object>> iPage;
        if(host == null){
            iPage = hostMapper.getUserCallContents(p, userId);
        }else{
            iPage = hostMapper.getHostCallContents(p, userId, status);
        }

        List<Map<String, Object>> callContents = iPage.getRecords();

        data.put("callContents", callContents);
        return Result.returnSuccess(data);
    }

    @Override
    public Result getUserOperations(String token, Integer page, Integer limit) throws Exception {
        Map<String, Object> data = new HashMap<>();

        Integer userId = commonService.getUserId(token);

        List<Map<String, Object>> operations = hostMapper.getUserOperation(userId, 0, PageUtil.getOffset(page, limit), limit);

        data.put("operations", operations);
        return Result.returnSuccess(data);
    }

    @Override
    public Result callUser(String token, Integer operationLogId, Integer contentId) throws Exception {
        Map<String, Object> data = new HashMap<>();
        Integer userId = commonService.getUserId(token);

        Host host = hostMapper.selectByUserId(userId);
        if(host == null){
            return Result.returnFailure("用户并非主播，不能打招呼");
        }
        Map<String, Object> hostCallLog = hostMapper.getHostCallLog(userId, operationLogId);
        if(hostCallLog != null){
            return Result.returnFailure("已经打过招呼，无需重复");
        }
        hostMapper.saveHostCallLog(userId, operationLogId, contentId);

        HostCallContent hostCallContent = hostCallContentMapper.selectById(contentId);
        data.put("callContent", hostCallContent);

        return Result.returnSuccess(data);
    }

    @Override
    public Result getUserHomeBrief(String token, Integer toUserId) throws Exception {
        Map<String, Object> data = new HashMap<>();

        Integer userId = commonService.getUserId(token);

        Map<String, Object> user = hostMapper.getUserHomeBrief(userId, toUserId);

        data.put("user", user);
        return Result.returnSuccess(data);
    }

    @Override
    public Result getUserHome(String token, Integer toUserId) throws Exception {
        Map<String, Object> data = new HashMap<>();

        Integer userId = commonService.getUserId(token);

        //记录访问记录
        if(userId != null){
            baseService.addAccessLog(userId, toUserId);
        }

        Map<String, Object> userMap = hostMapper.getUserHome(userId, toUserId);
        List<Map<String, Object>> photos = hostMapper.getHostPhotos(toUserId);
        userMap.put("photos", photos);

        data.put("user", userMap);
        return Result.returnSuccess(data);
    }

    @Override
    public Result getUserInfo(String token, Integer toUserId) throws Exception {
        Map<String, Object> data = new HashMap<>();
        Integer userId = commonService.getUserId(token);

        Map<String, Object> userInfo = hostMapper.getUserInfo(userId, toUserId);
        //映像标签
        List<Map<String, Object>> lables = userLableMapper.getUserLables(toUserId);
        //用户评价标签
        List<Map<String, Object>> userToHostLables = hostMapper.getUserToHostLables(toUserId);
        //礼物
        Host host = hostMapper.selectByUserId(toUserId);
        List<Map<String, Object>> gifts = userGiftBuyLogMapper.getUserGifts(toUserId, host == null ? 0 : 1);
        //评价
//        List<Map<String, Object>> likes = hostMapper.getHostLike(toUserId);

        userInfo.put("lables", lables);
        userInfo.put("userLables", userToHostLables);
        userInfo.put("gifts", gifts);

//        userInfo.put("goodNum", 0);
//        userInfo.put("badNum", 0);
//        for(Map<String, Object> map : likes){
//            int type = Integer.parseInt(map.get("type")+"");
//            int num = Integer.parseInt(map.get("num")+"");
//            if(type == 0){
//                userInfo.put("goodNum", num);
//            }else if(type == 1){
//                userInfo.put("badNum", num);
//            }
//        }

        if(host != null){
            userInfo.put("updateTime", null);
        }

        data.put("userInfo", userInfo);
        return Result.returnSuccess(data);
    }

    @Override
    public Result getHostEvaluates(String token, Integer hostUserId, Integer page, Integer limit) throws Exception {
        Map<String, Object> data = new HashMap<>();

        Page<Map<String, Object>> p = new Page<>(page, limit);
        IPage<Map<String, Object>> iPage = hostMapper.getHostEvaluates(p, hostUserId);
        List<Map<String, Object>> evaluates = iPage.getRecords();
        for(Map<String, Object> evaluate : evaluates){
            Integer logId = Integer.parseInt(evaluate.get("logId")+"");
            List<Map<String, Object>> lables = hostMapper.getLogLables(logId);
            evaluate.put("lables", lables);
        }

        data.put("evaluates", evaluates);
        return Result.returnSuccess(data);
    }

    @Override
    public Result getUserDynamic(String token, Integer toUserId, Integer page, Integer limit) throws Exception {
        Map<String, Object> data = new HashMap<>();

        Integer userId = commonService.getUserId(token);
        Page<Map<String, Object>> p = new Page<>(page, limit);
        IPage<Map<String, Object>> iPage = userDynamicMapper.getUserDynamic(p, userId, toUserId);
        List<Map<String, Object>> dynamics = iPage.getRecords();

        dynamicService.handleDynamic(dynamics);

        data.put("dynamics", dynamics);
        return Result.returnSuccess(data);
    }

    /**
     * 搜索
     * @Author Shane
     * @Date 2019/10/10 22:14
     * @param
     * @return
     */
    @Override
    public Result search(String token, String keyword, Integer page, Integer limit) throws Exception {
        Map<String, Object> data = new HashMap<>();
        Integer userId = commonService.getUserId(token);

        Host host = null;
        if(userId != null){
            host = hostMapper.selectByUserId(userId);
        }

        List<Map<String, Object>> users = new ArrayList<>();
        if(host == null){
            users = hostMapper.getRandomHosts(userId, keyword, PageUtil.getOffset(page, limit), limit);
        }else{
            users = userMapper.getRandomUsers(userId, keyword, PageUtil.getOffset(page, limit), limit);
        }

        data.put("users", users);
        return Result.returnSuccess(data);
    }

    @Override
    public Result getUserOperationLog(String token, Integer curr) throws Exception {
        Map<String, Object> data = new HashMap<>();

        if(curr == null){
            curr = 0;
        }

        Page<Map<String, Object>> page = new Page<>(1, 20);
        IPage<List<Map<String, Object>>> ops = userOperationLogMapper.getUserOperationInfo(page, curr);

        data.put("operations", ops.getRecords());

        return Result.returnSuccess(data);
    }

}
